//! @Author: DengLibin
//! @Date:  2022-04-19 15:42:14
//! @Description: 日期模块 NaiveDateTime不带时区的时间 。UTC 本身没有时区的概念 是一种基准时间，所有其他时区都是基于 UTC 偏移的

use std::{ops::Add, time::SystemTime};

use chrono::{DateTime, Datelike, Duration, Local, NaiveDateTime, Utc};
use chrono_tz::Tz;
const DATE_TIME_PATTERN: &str = "%Y-%m-%d %H:%M:%S";

//////////////////////////////////////获取时间戳,以下几种获取的是时间戳相同//////////////////////////////////////////
///获取时间戳 毫秒
pub fn get_sys_timestamp_millis() -> u128 {
    let now = SystemTime::now();
    now.duration_since(SystemTime::UNIX_EPOCH)
        .unwrap()
        .as_millis()
}
///获取时间戳 毫秒
pub fn get_chrono_timestamp_millis() -> i64 {
    let now = Local::now().naive_local();
    now.and_utc().timestamp_millis()
}

//获取当前时间 秒 utc时间(0时区)
pub fn get_utc_timestamp() -> i64 {
    Utc::now().timestamp()
}

//获取本地当前时间 的utc时间戳 秒
pub fn get_local_date_time_utc_timestamp() -> i64 {
    let now = Local::now().naive_local();
    now.and_utc().timestamp()
}

//////////////////////////////////////获取时间戳//////////////////////////////////////////

//获取当前时间 utc时间(无时区)
pub fn get_date_time_utc_now() -> DateTime<Utc> {
    Utc::now()
}

//获取本地当前时间转utc时间
pub fn get_local_date_time_utc_now() -> DateTime<Utc> {
    let now = Local::now().naive_local();
    now.and_utc()
}

///获取本地当前时间 格式化
pub fn get_chrono_local_now_time_str() -> String {
    let now = Local::now().naive_local();
    format_time(&now)
}
///获取年
pub fn get_chrono_local_now_year() -> i32 {
    let now = Local::now().naive_local();
    now.year()
}
///获取月
pub fn get_chrono_local_now_month() -> u32 {
    let now = Local::now().naive_local();
    now.month()
}
///获取日
pub fn get_chrono_local_now_day() -> u32 {
    let now = Local::now().naive_local();
    now.day()
}
///获取年 月 日
pub fn get_chrono_now_year_month_day() -> (i32, u32, u32) {
    let now = Local::now().naive_local();
    (now.year(), now.month(), now.day())
}
///时间戳转日期
pub fn timestamp2datetime_str(timestamp_sec: i64) -> String {
    let time_option = timestamp2datetime(timestamp_sec);
    if let Some(time) = time_option {
        return format_time(&time);
    };
    return "".to_string();
}

/// 时间字符串戳转日期
/// 返回时间戳（毫秒）
pub fn timestr2date(datetime: &str) -> Result<i64, String> {
    let r = NaiveDateTime::parse_from_str(datetime, DATE_TIME_PATTERN);

    match r {
        Ok(t) => Ok(t.and_utc().timestamp_millis()),
        Err(e) => Err(e.to_string()),
    }
}
/// 时间字符串转utc时间
pub fn timestr2time_utc(datetime: &str) -> Result<DateTime<Utc>, String> {
    let r = NaiveDateTime::parse_from_str(datetime, DATE_TIME_PATTERN);

    match r {
        Ok(t) => {
            let timestamp_millis = t.and_utc().timestamp_millis();
            let o = DateTime::from_timestamp_millis(timestamp_millis);
            return if let Some(date_time) = o {
                Ok(date_time)
            } else {
                Err(format!("日期转换错误:{}-{}", datetime, timestamp_millis))
            };
        }
        Err(e) => Err(e.to_string()),
    }
}
pub fn timestr2time_naive(datetime: &str) -> Result<NaiveDateTime, String> {
    let r = NaiveDateTime::parse_from_str(datetime, DATE_TIME_PATTERN);

    match r {
        Ok(t) => Ok(t),
        Err(e) => Err(e.to_string()),
    }
}
/// 相加 天数 返回时间戳 毫秒
pub fn add_day(timestamp_sec: i64, day: i64) -> i64 {
    let date_option = timestamp2datetime(timestamp_sec);
    if let Some(date) = date_option {
        let d = date.add(Duration::try_days(day).unwrap());
        return d.and_utc().timestamp_millis();
    }
    return 0_i64;
}

/// 格式化日期
pub fn format_time(time: &NaiveDateTime) -> String {
    time.format(DATE_TIME_PATTERN).to_string()
}
/// 时间戳(秒)转日期
pub fn timestamp2datetime(timestamp_sec: i64) -> Option<NaiveDateTime> {
    let r = DateTime::from_timestamp(timestamp_sec, 0);
    if let Some(date_time) = r {
        //更正时区为上海
        Some(date_time.with_timezone(&Tz::Asia__Shanghai).naive_local())
    } else {
        None
    }
}

/// 时间戳(毫秒)转日期
pub fn mill_timestamp2datetime(timestamp_millis: i64) -> Option<NaiveDateTime> {
    let o = DateTime::from_timestamp_millis(timestamp_millis);
    if let Some(date_time) = o {
        Some(date_time.naive_local())
    } else {
        None
    }
}

pub fn tz_demo() {
    // UTC时间
    let now_utc = Utc::now();
    println!("Current UTC time: {}", now_utc);

    // 创建当前本地时间
    let now_local = Local::now();
    println!("Current local time: {}", now_local);
    // 转换为 UTC 时间
    let now_utc = now_local.with_timezone(&Utc);
    println!("Converted UTC time: {}", now_utc);
    println!("中国时区");

    // 创建一个 UTC 时间实例
    let utc_time = Utc::now();

    // 获取中国时区的实例
    let china_tz = Tz::Asia__Shanghai; // 使用 "Asia__Shanghai" 作为中国时区的代表

    // 将 UTC 时间转换为中国时区的时间
    let china_time = utc_time.with_timezone(&china_tz);

    // 打印中国时间
    println!("China time: {}", china_time);
}
